defmodule DdlUtil do
    @moduledoc false

    def write_sql_to_file(schema) do
        s = global_tables()
            |> Enum.reduce(
                   [],
                   fn
                       mod, acc ->
                           Process.sleep(10)
                           PsqlSchema.get_sql(mod, schema) ++ acc
                   end
               )
        File.write!("./sql.exs", inspect(s))
    end


    # 先改数据库, 再去对应模块添加对应的项
    def update_column(uids, mod, column, type) do
        PsqlDb.transaction(
            fn () ->
                Enum.each(
                    uids,
                    fn (uid) ->
                        table = get_table(mod, uid)
                        Map.get(mod.fields(), column) != nil &&
                            "ALTER TABLE #{table} DROP COLUMN #{column}"
                            |> PsqlDb.query!()
                        "ALTER TABLE #{table} ADD COLUMN #{column} #{PsqlSchema.convert_type(type)}"
                        |> PsqlDb.query!()
                    end
                )
            end
        )
    end

    def add_column(uids, mod, column, type) do
        Enum.each(
            uids,
            fn (uid) ->
                "ALTER TABLE #{get_table(mod, uid)} ADD COLUMN #{column} #{PsqlSchema.convert_type(type)}"
                |> PsqlDb.query!()
            end
        )
    end


    def drop_column(uids, mod, column) do
        Enum.each(
            uids,
            fn (uid) ->
                "ALTER TABLE #{get_table(mod, uid)} DROP COLUMN #{column}"
                |> PsqlDb.query!()
            end
        )
    end

    def create_table(proj_uids) when is_list(proj_uids) do
        tables = schema_tables()
#        Enum.each(
#            proj_uids,
#            fn (uid) ->
#                if uid != nil do
#                    "CREATE SCHEMA #{inspect(uid)}"
#                    |> PsqlDb.query()
#                end
#            end
#        )
        Enum.each(
            tables,
            fn
                mod ->
                    Process.sleep(50)
                    Enum.each(proj_uids, &PsqlSchema.create_table(mod, &1))
            end
        )
    end
    def create_table(uid) do
        create_table([uid])
    end

    def create_global_table() do
        PsqlDb.transaction(
            fn () ->
                Enum.each(
                    global_tables(),
                    fn
                        mod ->
                            Process.sleep(50)
                            PsqlSchema.create_table(mod, nil)
                    end
                )
            end
        )
    end

    def delete_table(uids, mod) do
        PsqlDb.transaction(
            fn () ->
                Enum.each(
                    uids,
                    fn (uid) ->
                        "DROP TABLE #{get_table(mod, uid)};"
                        |> PsqlDb.query()
                    end
                )
            end
        )
    end

    def delete_table(proj_uids) when is_list(proj_uids) do
        drops = schema_tables()
        PsqlDb.transaction(
            fn () ->
                Enum.each(
                    drops,
                    fn
                        mod ->
                            Enum.each(
                                proj_uids,
                                fn (uid) ->
                                    "DROP TABLE #{get_table(mod, uid)};"
                                    |> PsqlDb.query()
                                end
                            )
                    end
                )
            end
        )
    end
    def delete_table(uid) do
        delete_table([uid])
    end



    def schema_tables(path \\ File.cwd! <> "/lib/db/") do
        get_db_mod(path, [], false)
    end

    def global_tables(path \\ File.cwd! <> "/lib/db/") do
        get_db_mod(path, [], true)
    end


    def get_db_mod(path, mods, is_global) do
        File.ls!(path)
        |> Enum.reduce(
               mods,
               fn dir, acc ->
                   path = path <> "/" <> dir
                   if File.dir?(path) do
                       get_db_mod(path, acc, is_global)
                   else
                       mod = [Macro.camelize(Path.rootname(dir))]
                             |> Module.concat()
                       mod.module_info(:md5)
                       if :erlang.function_exported(mod, :db_type, 0) && mod.db_type() == Pango.DbType.pg() &&
                              (is_global && mod.is_global() || (!is_global && !mod.is_global())) do
                           [mod | acc]
                       else
                           acc
                       end
                   end

               end
           )
    end


    def get_table(mod, uid) do
        if uid == nil do
            mod.get_table()
        else
            "#{inspect(uid)}.#{mod.get_table()}"
        end
    end

end
